import { $createNodeSelection, $getRoot, $getSelection, $isRangeSelection, $setSelection, DecoratorNode, EditorConfig, NodeKey } from 'lexical';
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';

import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';
import { Dropdown, MenuProps, Space } from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import useVariable from '../store/useVariable';


// 2. 正确定义 ComponentNode 类
class ComponentNode extends DecoratorNode<JSX.Element> {
  __content: Variable;

  static getType(): string {
    return 'component';
  }

  static clone(node: ComponentNode): ComponentNode {
    // 确保克隆时传递 key
    return new ComponentNode(node.__content, node.__key);
  }

  constructor(content: Variable, key?: string) {
    super(key);
    this.__content = content;
  }

  createDOM(config: EditorConfig): HTMLElement {
    const div = document.createElement('div');
    div.style.display = 'inline';
    return div;
  }

  updateDOM(): boolean {
    return false;
  }

  decorate(): JSX.Element {
    return (
      <div style={{
        display: 'inline-flex',
        background: 'white',
        color: '#6172F3',
        paddingInline: 4,
        marginInline: 4,
        borderRadius: 4,
      }}>
        <img
          src="img/fluent--braces-variable-24-filled.svg"
          style={{ height: 18, transform: 'translateY(4px)' }}
        />
        <span>{this.__content?.label}</span>
      </div>
    );
  }

  // 添加序列化方法
  exportJSON() {
    return {
      type: this.getType(),
      version: 1,
      // 可以添加需要保存的其他数据
      content: this.__content
    };
  }

  // 反序列化方法
  static importJSON(serializedNode: any): ComponentNode {
    const node = new ComponentNode(serializedNode.content);
    return node;
  }
}


function onError(error) {
  throw error;
}

interface InsertComponentButtonProps {
  title: string;
}

// 1. 创建插入按钮组件
function InsertComponentButton(props: InsertComponentButtonProps) {
  const [editor] = useLexicalComposerContext();
  const { variable } = useVariable()
  const [items, setItems] = useState<MenuProps['items']>([])

  const insertComponent = (variableEdit: Variable) => {
    editor.update(() => {
      const selection = $getSelection();
      if ($isRangeSelection(selection)) {
        const node = new ComponentNode(variableEdit);
        selection.insertNodes([node]);

        // 创建新的节点选择
        const nodeSelection = $createNodeSelection();
        nodeSelection.add(node.getKey());
        $setSelection(nodeSelection);
      }
    });
  };

  useEffect(() => {
    const data = variable.map((item) => {
      return {
        key: item.id,
        label: (
          <div className='text-[#1877FF] w-full' onClick={() => { insertComponent(item) }}>
            {item.label}
          </div>
        ),
      }
    })
    setItems(data)
  }, [variable])

  return (
    <div className='flex justify-between w-full font-bold'>
      <div className='flex items-center ml-[10px]'>
        <div>{props.title}</div>
        <QuestionCircleOutlined className='ml-1' />
      </div>
      <Dropdown
        menu={{
          items
        }}
      >
        <a onClick={(e) => e.preventDefault()}>
          <Space style={{ color: "#1877FF", padding: 10, fontSize: 14 }}>
            <img src='img/fluent--braces-variable-24-filled.svg' style={{ height: 18 }} />
            变量
          </Space>
        </a>
      </Dropdown>
    </div>
  );
}

export interface LexicalEditRef {
  setData: (data: string) => void;
  onFocus: () => void;
}

// 加载节点
const LoadNode = forwardRef<LexicalEditRef, {}>((props, ref) => {
  const [editor] = useLexicalComposerContext();
  useImperativeHandle(ref, () => ({
    setData: (data) => {
      try {
        const initialEditorState = editor.parseEditorState(data);
        editor.setEditorState(initialEditorState);
      } catch (e) {
        console.error("解析错误", e)
      }
    },
    onFocus: () => {
      editor.focus();
    }
  }));
  return null
})

interface Props {
  onChange?: (editorState: string) => void;
  title?: string;
  value?: string;
  height?: number;
}

// 富文本编辑器
const LexicalEdit = (props: Props) => {
  const { onChange, value, title = "回复", height = 300 } = props
  const ref = useRef<LexicalEditRef>(null)
  const isInitializedRef = useRef(false);

  useEffect(() => {
    if (value && !isInitializedRef.current) {
      ref.current?.setData(value);
      isInitializedRef.current = true;
      setTimeout(() => {
        ref.current?.onFocus();
      }, 0);
    }
  }, [value]);

  const initialConfig = {
    namespace: 'Editor',
    theme: {},
    onError,
    nodes: [ComponentNode]
  };

  return (
    <div
      onClick={event => { event.stopPropagation() }}
      onMouseDown={event => { event.stopPropagation() }}
      className='p-[2px] rounded-lg bg-[#F2F4F7] text-[#475467] text-[14px]'>
      <LexicalComposer
        initialConfig={initialConfig}
      >
        <InsertComponentButton title={title} />
        <PlainTextPlugin
          placeholder={<div className='relative'>
            <div className='absolute left-3 text-[#AFB1B9] pointer-events-none'
              style={{ bottom: height - 22 }}
            >请输入内容...</div>
          </div>}
          contentEditable={<ContentEditable
            className='contentEditable'
            style={{
              outline: 'none',
              overflow: 'auto',
              height,
              padding: "0px 10px 0px 10px",
            }}
          />}
          ErrorBoundary={LexicalErrorBoundary} />
        <OnChangePlugin onChange={(editorState) => {
          const data = editorState.toJSON();
          onChange(JSON.stringify(data));
        }} />
        <HistoryPlugin />
        <LoadNode ref={ref} />
      </LexicalComposer>
    </div>
  );
}

export default LexicalEdit;

